/**
 * @file    woshshop.cpp
 * @brief   WOSH WorkShop [woshshop], Multiplatform.
 *
 *          Initialize QT GUI, application's resources, wosh::WoshKernel
 *          and configuration, dynamic allocators, prompt a splash while
 *          loading.
 *
 *          Tested with:
 *            - Microsoft Visual Studio 2008, QT 4.5 for Windows32
 *            - GCC 4.1, QT 4.4
 *
 *
 * \see     wosh::application::WoshShopWindow
 *
 ****************************************************************************
 * \section page_applications_woshshop WOSH WorkShop [Multiplatform]
 *
 * WOSH WorkShop is a multi-document application developed under Windows,
 * but works on any platform.
 *
 *
 * Here are some screenshots:
 * \image html extras/screenshots/WOSH.WorkShop.1.png "WOSH WoskShop screenshot"
 * \image html extras/screenshots/WOSH.WorkShop.2.png "WOSH WoskShop screenshot"
 * \image html extras/screenshots/WOSH.WorkShop.3.png "WOSH WoskShop screenshot"
 * \image html extras/screenshots/WOSH.WorkShop.4.png "WOSH WoskShop screenshot"
 *
 *
 ****************************************************************************
 * @version 0.8.161 $Id: woshshop.cpp 2882 2010-08-09 11:08:30Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/

#define _CONFIG_FILE		"../etc/wosh/wosh.workshop.conf"
#define _LOG_FILE			"../var/log/wosh.workshop.log"

#include <core/WoshKernel.h>
#include <core/ObjectFactory.h>
#include <core/BundleManager.h>
#include <core/SessionManager.h>
#include <core/BusManager.h>
#include <core/LogHandlers.h>
#include <framework/gui/components/BusRingQt.h>
#include <framework/gui/GuiUtilities.h>
#include <framework/gui/dialogs/DialogLogin.h>

 #include <framework/security/SecurityAuthenticationOS.h>
#include <bundles/services/DesktopNotifier/DesktopNotifierBundle.h>

//////////////////////////////////////////////////////////////////
#include "WoshShopWindow.h"
#include <QApplication>
#include <QtGui>


using namespace wosh;
using namespace wosh::gui;
using namespace wosh::application;

int main( int argc, char **argv )
 {
	//////////////////////////////////////////////////////////////////////////////////////
	// init QT and its resources
	Q_INIT_RESOURCE(woshshop);
	QApplication app(argc, argv);

	//////////////////////////////////////////////////////////////////////////////////////
	// splash screen
	QSplashScreen splash( QPixmap(":/wosh.splash.icarus.png") );
	splash.setFont( QFont("Tahoma", 12, 1, false) );
	splash.showMessage("Initializing..", Qt::AlignBottom);
	splash.show();
	app.processEvents();

	//////////////////////////////////////////////////////////////////////////////////////
	// setup defauld Log-handler
	DefaultSharedLogHandler::getInstance()->setFileName( _LOG_FILE );
	DefaultSharedLogHandler::getInstance()->setStdOut(false);

	//////////////////////////////////////////////////////////////////////////////////////
	splash.showMessage("Loading Settings..", Qt::AlignBottom, QColor(Qt::white)); app.processEvents();
	//////////////////////////////////////////////////////////////////////////////////////
	// load settings for command line arguments, default configuration file and folders
	// WOSH configuration architecture is similar to Apache2
	Settings* woshSettings = new Settings();
	woshSettings->loadFromArgs(argc, argv);

	std::string cfgFile = woshSettings->getValueOf( "", "ConfigFile", _CONFIG_FILE ).toString();
	WRESULT loaded = woshSettings->loadConfigurationFile( cfgFile );
	while ( loaded != WRET_OK ) {
		GuiUtilities::aboutError_woshconf( NULL, cfgFile );
		QString fileName = QFileDialog::getOpenFileName(NULL, "Open WOSH configuration file", "../etc/wosh", "Configuration file (*.conf);;All files (*.*)" );
		if ( fileName.isNull() )
			return WRET_ERR_PARAM;
		cfgFile.assign( fileName.toLatin1().data() );
		loaded = woshSettings->loadConfigurationFile( cfgFile );
	 }
	std::string woshName = woshSettings->getValueOf( "WoshKernel", "Name", "" ).toString();

	//////////////////////////////////////////////////////////////////////////////////////
	splash.showMessage( QString("Allocating WoshKernel [%1]..").arg(woshName.c_str()), Qt::AlignBottom, QColor(Qt::white)); app.processEvents();
	//////////////////////////////////////////////////////////////////////////////////////
	// alloc Kernel
	WoshKernel core( woshName, woshSettings );

	//////////////////////////////////////////////////////////////////////////////////////
	splash.showMessage( QString("Initializing Kernel [%1]..").arg(woshName.c_str()), Qt::AlignBottom, QColor(Qt::white)); app.processEvents();
	//////////////////////////////////////////////////////////////////////////////////////
	// now we installed and configured all CORE modules, we can init kernel (them)
	// (so bundles will be loaded, if autoload is set)
	core.init();

	//////////////////////////////////////////////////////////////////////////////////////
	splash.showMessage( "Initializing GUI Bus..", Qt::AlignBottom, QColor(Qt::white)); app.processEvents();
	//////////////////////////////////////////////////////////////////////////////////////
	// install custom BUS for the GUI (required cos of multi-threading vs. message passing)
	core.busses().registerBus( new BusRingQt(_Bus_Gui) );

	//////////////////////////////////////////////////////////////////////////////////////
	splash.showMessage( QString("Starting Kernel [%1]..").arg(woshName.c_str()), Qt::AlignBottom, QColor(Qt::white)); app.processEvents();
	//////////////////////////////////////////////////////////////////////////////////////
	// enter loop (acquire thread), it will set kernel-state to running
	// (so bundles will start, if autostart is set)
	core.start();

	//////////////////////////////////////////////////////////////////////////////////////
	splash.showMessage( "Initializing GUI..", Qt::AlignBottom, QColor(Qt::white)); app.processEvents();
	//////////////////////////////////////////////////////////////////////////////////////
	// setup main window
	WoshShopWindow* win = new WoshShopWindow();

	std::string username = "anonymous";
	wosh::SecurityTokenProvider* sec = NULL;
	wosh::security::SecurityTokenProviderOS::findLoggedUser(username);
	wosh::security::SecurityTokenProviderOS secOS;
	WRESULT ret = DialogLogin::waitValidUser(username, &secOS, &sec);
	if ( WFAILED(ret) ) {
		core.shutdown();
		delete win; win = NULL;
		return WRET_ERR_SECURITY;
	 }
	GuiSession::getInstance().setUsernameLogged(username);
	GuiSession::getInstance().setCredentials(sec);
	GuiSession::getInstance().login();
	GuiSession::getInstance().open();
	core.sessions().registerSession( &GuiSession::getInstance() );

	//////////////////////////////////////////////////////////////////////////////////////
	win->init();

	//////////////////////////////////////////////////////////////////////////////////////
	splash.showMessage( "Installing Desktop-Notifier Bundle..", Qt::AlignBottom, QColor(Qt::white)); app.processEvents();
	//////////////////////////////////////////////////////////////////////////////////////
	// setup DesktopNotifier
	wosh::services::DesktopNotifierBundle* dNot = ObjectFactory::createTypeOf<wosh::services::DesktopNotifierBundle>();
	if ( dNot != NULL ) {
		dNot->setTrayIcon(win->getTrayIcon());
		win->setDesktopNotifierBundle(dNot);
		core.bundles().installBundle( dNot );
	 }
	else {
		QMessageBox::warning(win, "WOSH WorkShop",
			QString(	"<h1>WOSH WARNING</h1>"
						"<h2>wosh::services::DesktopNotifierBundle is not available!</h2>") );
	 }
	//////////////////////////////////////////////////////////////////////////////////////
	win->show();
	splash.finish(win);

	//////////////////////////////////////////////////////////////////////////////////////
	// let QT acquire thread
	int app_ret = app.exec();

	//////////////////////////////////////////////////////////////////////////////////////
	core.sessions().unRegisterSession( &GuiSession::getInstance() );
	//////////////////////////////////////////////////////////////////////////////////////
	// exiting.. shutdown kernel
	core.shutdown();

	//////////////////////////////////////////////////////////////////////////////////////
	delete win; win = NULL;

	//////////////////////////////////////////////////////////////////////////////////////
	return app_ret;
 }
